#ifndef MYDISK_H_
#define MYDISK_H_

#include <stdio.h>
#include <vector>
#include "Defines.h"
#include "SuperBlock.h"


class MyDisk
{
public:
	/**
	 * super block 0 == diskSize
	 * super block 4 == blockSize
	 * super block 8 == inode number
	 * super block 12 == pointer of free list
	 * super block 16 == size of free list
	 * super block 20 == pointer to the next free node
	 * super block 24 == size of inode free list
	 *
	 * */

	SuperBlock SB;
	FILE *pFile;

	int freeListSize;
	int numberOfBlocksForInodeArray;
	int numberOfBlocksForFreeInodes;
	MyDisk();
	/**
	 * isNew true for new FILE_SYS
	 *
	 */
	MyDisk(int _diskSize, int _blockSize, int _numOfNodes,bool isNew);
	/**
	 * possible only if the super is init in the file
	 */
	void initSB();
	void init(long numOfBytes);

	int initFreeListInode();

//	void initFreeList();
//	int helperFreeList(int length,int currFreeBlock,int ref,int curBlock,int last);

	virtual ~MyDisk();


	void sprintb(char *s, unsigned n);
	/**
	 * ans is the pointer what we read
	 * offset is the position in the file
	 * size is how many bytes to read
	 *
	 * */
	int read(unsigned char* ans,long offset,int size);
	/**
	 * y is the char we put in
	 * offset the position in the file
	 *
	 */
	int write(unsigned char* y,long offset);
	/**
	 * number the number you want to write into the file
	 * offset the position in the file	 *
	 */


	int writeInt(int number,long offset);
	/**
	 * offset the position in the file
	 */
	int readInt( long offset);
	/**
	 */
	int writeChar(char* str,long offset, int size);
	/**
	 * str is the ans
	 *
	 */
	int readChar(char* str,long offset,int size);

	/**
	 * return the offset of the requested block
	 */
	long getBlockOffset(int dblockNum);

	//updating the pointer to the next free block
	void updateFListPtr(long num);

	bool isFreeBlock(int dblock);

	void initInode(int inode);

	int numberOfFreeBlocks();

	int numberOfFreeInodes();

	int calcInodeArray();


	int freeInodeToInodeNumber(int ref);

	int inodeToFreeAddress(int inode);



	void initIndirectBlock(int dBlock);

	int sizeOfIndirectBlock(int dBlock);

	int putNextBlock(int dBlock , int newDblock);

	int deleteInDirectBlock(int dBlock);



	//return the offset of the I node
	int getInode(int index);

	//return the index from the offset
	int getInodeIndex(int offset);

	//check if this inode is free
	bool isFreeInode(int index);

	//write inode Number of hardLink
	int setInodeHlink(int index,char* c);

	//read inode number of hardLinks
	char getInodeHlink(int index);

	//
	int addInodeToFreeList(int inode);

	int blockToAddress(int block);

	int addressToBlock(int address);

	//return the size of the total size of free inode list
	int calcInodeFreeListSize();

	//printing the free list
	void printFList();

	void printSuperBlock();

	void printFreeInodeList();

	void printInode(int inode);

	void printInDirectBlock(int dBlock);


//*~~~~~~~~~ low level disk services~~~~~~~~~~~~~~~~~~~~~``` *//
	int writeBlock(int dblockNum, char* newdata);

	int readBlock(int dblockNum, char* buf);

	int allocateDataBlock();

	int freeDataBlock(int dblock);

	int allocateInode();

	//write inode tpye
	int setInodeType(int index,char* c);

	//read inode type
	char getInodeType(int index);


	//write inode size of file
	int setFileSize(int index,int size);

	//read inode size of file
	int getFileSize(int index);

	/*write to inode block addres at place
	 * index - the index of a block
	 * place the place of the addres in the inode (place == 0 - 9 or 10 for indorect)
	 * addres the block address
	 */
	int setDataBlock(int index,int place, int dBlock);

	//read inode block address at place
	int getDataBlock(int index, int place);

	/*write to inode block addres at place
	 * index - the index of a block
	 * place the place of the addres in the inDirect address
	 * addres the block address
	 */
	int setInDirectDataBlock(int index,int place, int dBlock);

	//read inode block address at place
	int getInDirectDataBlock(int inode, int place);

	int freeInode(int inode);

	int deleteInode(int inode);


};

#endif /*MYDISK_H_*/
